package org.springblade.modules.admin.service.suger.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.io.IORuntimeException;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.core.tool.utils.Func;
import org.springblade.modules.admin.dto.sugar.EstateTlwGeneralDTO;
import org.springblade.modules.admin.dto.tlw.TlwRescuePlanChangeStateDTO;
import org.springblade.modules.admin.dto.video.TicketFeedBackDTO;
import org.springblade.modules.admin.service.ElevatorDeviceService;
import org.springblade.modules.admin.service.IEstateBuildingService;
import org.springblade.modules.admin.service.suger.IEstateTlwScreenService;
import org.springblade.modules.admin.utils.TlwEmsUtil;
import org.springblade.modules.admin.utils.TlwUtil;
import org.springblade.modules.admin.vo.DeviceStatusVO;
import org.springblade.modules.admin.vo.EstateElevatorVO;
import org.springblade.modules.admin.vo.SimpleElevatorInfoVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Description
 * @Author ysq
 * @Date 2022/12/26
 **/
@Slf4j
@Service
public class EstateTlwScreenServiceImpl implements IEstateTlwScreenService {

	@Autowired
	private IEstateBuildingService estateBuildingService;

	@Autowired
	private ElevatorDeviceService elevatorDeviceService;

	@Autowired
	private TlwUtil tlwUtil;

	@Autowired
	private TlwEmsUtil tlwEmsUtil;

	@Value("${ems.url}")
	private String tlwEmsUrl;

	@Value("${ems.timeout}")
	private Integer timeout;

	@Override
	public JSONObject general(EstateTlwGeneralDTO estateTlwGeneralDTO) {
		List<EstateElevatorVO> elevatorList = estateBuildingService.estateElevatorList(AuthUtil.getTenantId());
		// 电梯总数
		long elevatorCount = elevatorList.stream().count();
		// 已开通梯联网电梯数
		long tlwCount = elevatorList.stream().filter(t -> t.getTlwStatus() == 2 || t.getTlwStatus() == 3).count();

		List<String> deviceIds = elevatorList.stream().filter(t -> (t.getTlwStatus() == 2 || t.getTlwStatus() == 3) && t.getDeviceId() != null).map(t -> t.getDeviceId()).collect(Collectors.toList());
		if (Func.isEmpty(deviceIds)) {
			return new JSONObject();
		}

		String url = "/property/v1/overView/general";
		estateTlwGeneralDTO.setDeviceIds(deviceIds);
		Map<String, Object> paramMap = BeanUtil.beanToMap(estateTlwGeneralDTO);
		String result= null;
		try {
			result = tlwUtil.get(url, paramMap);
		}catch (IORuntimeException e) {
			throw new ServiceException("梯联网数据返回异常!");
		}

		JSONObject jsonObj = JSONUtil.parseObj(result, true);
		if ("200".equals(String.valueOf(jsonObj.get("code"))) && Func.isNotEmpty(String.valueOf(jsonObj.get("data")))) {
			JSONObject jsonDataObj = JSONUtil.parseObj(jsonObj.get("data"));
			if (Func.isNotEmpty(String.valueOf(jsonDataObj.get("onlineCount")))) {
				long onlineCount = jsonDataObj.getLong("onlineCount");
				long offlineCount = tlwCount - onlineCount;
				jsonDataObj.putOpt("elevatorCount", elevatorCount);
				jsonDataObj.putOpt("tlwCount", tlwCount);
				jsonDataObj.putOpt("offlineCount", offlineCount);
			}
			jsonObj.set("data", jsonDataObj);
		}

		return jsonObj;
	}

	@Override
	public boolean ticketFeedback(TicketFeedBackDTO feedBack) {
		String url = "/v1/data/ticketFeedback";
		Map<String, Object> paramMap = BeanUtil.beanToMap(feedBack);
		String result;
		log.info("反馈工单状态接口地址：{}，参数{}",tlwEmsUrl + url, JSONUtil.toJsonStr(paramMap));
		try {
			result = HttpUtil.createPost(tlwEmsUrl+url).body(JSONUtil.toJsonStr(paramMap)).execute().body();
			log.warn("梯联网回调结果：{}",result);
//			JSONObject jsonObj = JSONUtil.parseObj(result, true);
//			if(jsonObj.containsKey("success")){
//				return jsonObj.getBool("success");
//			}
			return true;
		}catch (IORuntimeException e) {
			log.error("调用反馈工单状态接口异常!", e);
		}
		return Boolean.FALSE;
    }

	@Async
	@Override
	public void rescuePlanChangeState(TlwRescuePlanChangeStateDTO param) {
		log.info("=========== 同步更新梯联网救援工单状态：[{}] ===========", JSONUtil.toJsonStr(param));
		String url = "/ivh/v1/streamManager/changeState";
		String params = Func.toJson(param);
		try {
			tlwEmsUtil.post(url, params);
			log.info("=========== 同步更新梯联网救援工单状态：[{}] ===========", "成功");
		}catch (Exception e) {
			log.info("=========== 同步更新梯联网救援工单状态,异常：[{}] ===========", e.getMessage());
		}
	}


	@Override
	public Map<Long, DeviceStatusVO> getDeviceStatus(List<Long> elevatorIds) {
		if (Func.isEmpty(elevatorIds)) {
			throw new ServiceException("参数为空： {elevatorIds}");
		}

		Map<Long, DeviceStatusVO> resultMap = new HashMap<>(8);
		String url = "/property/v2/devices?elevatorIds=" + Func.join(elevatorIds);
		JSONObject result = null;
		try {
			result = JSONUtil.parseObj(tlwUtil.get(url, null));
		} catch (Exception e) {
			return resultMap;
		}

		if ("200".equals(result.getStr("code")) && Func.isNotEmpty(result.getStr("data"))) {
			JSONObject data = JSONUtil.parseObj(result.get("data"));
			JSONArray deviceStatusArr = JSONUtil.parseArray(data.get("deviceStatusList"));
			for (int i = 0; i < deviceStatusArr.size(); i++) {
				Long elevatorId = deviceStatusArr.getJSONObject(i).getLong("elevatorId");
				if (Func.isEmpty(elevatorId)) {
					continue;
				}
				DeviceStatusVO deviceStatusVO = JSONUtil.toBean(deviceStatusArr.getJSONObject(i), DeviceStatusVO.class);
				SimpleElevatorInfoVO elevatorInfo = elevatorDeviceService.getSimpleElevatorInfoByElevatorId(elevatorId);
				if (Func.isNotEmpty(elevatorInfo)) {
					deviceStatusVO.setBuildingId(elevatorInfo.getBuildingId());
					deviceStatusVO.setBuildingName(elevatorInfo.getBuildingName());
					deviceStatusVO.setElevatorAddress(elevatorInfo.getElevatorAddress());
				}
				resultMap.put(elevatorId, deviceStatusVO);
			}
		}

		return resultMap;
	}
}
